前言
今天听说了一个很有意思的需求,把Unity游戏打成一个包,嵌入到原生APP中
正好两种技术栈我都有过相关经验,所以手痒实现一下!
版本
Unity 2019.2.0f1
Xcode9.3.1
Show Me The Code
创建一个Unity工程
拖入一个Cube和Text控件
然后BuildSetting中切换到iOS
注意如果需要用模拟器调试 需要在
Player Settings
中把Other Settings
中的Target SDK
切换为Simulator SDK
Unity2019.2.0f中勾选
Auto Graphics API
并不会添加依赖需要手动取消
Auto Graphics API
并在Graphics APIs
中添加OpenGLES3
然后点击Build
iOS唤起Unity
Unity默认在iOS AppDelegate
中的applicationDidBecomeActive
调用一个startUnity:
方法
如果要自定义唤起时间,则需要改变这个方法的调用时机
在UnityAppController
修改并添加以下代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
- (void)applicationDidBecomeActive:(UIApplication*)application
{
::printf("-> applicationDidBecomeActive()\n");
[self removeSnapshotView];
if (_unityAppReady)
{
if (UnityIsPaused() && _wasPausedExternal == false)
{
UnityWillResume();
UnityPause(0);
}
if (_wasPausedExternal)
{
if (UnityIsFullScreenPlaying())
TryResumeFullScreenVideo();
}
UnitySetPlayerFocus(1);
}
else if (!_startUnityScheduled)
{
_startUnityScheduled = true;
// 替换startUnity:为startSelfIOSView
[self performSelector: @selector(startSelfIOSView) withObject: application afterDelay: 0];
}
_didResignActive = false;
}
// 创建原生页面和控件,自己控制唤起Unity时机
- (void)startSelfIOSView
{
UIViewController *vc = [[UIViewController alloc] init];
vc.view.frame = [UIScreen mainScreen].bounds;
vc.view.backgroundColor = [UIColor whiteColor];
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 200, 50)];
btn.backgroundColor = [UIColor blueColor];
[btn setTitle:@"跳转到Unity界面" forState:UIControlStateNormal];
// 按钮被点击时唤起Unity项目
[btn addTarget:self action:@selector(startUnity:) forControlEvents:UIControlEventTouchUpInside];
[vc.view addSubview:btn];
[_window addSubview:vc.view];
}
然后就可以通过我们的定义的时机唤起Unity了
Unity唤起iOS
因为Unity界面跳转到IOS界面涉及到了暂停Unity所以我们需要实现一个单例来判断Unity的暂停或启动
LARManager.h1
2
3
4
5
6
7
@interface LARManager : NSObject
/** 是否暂停Unity */
@property (assign, nonatomic) BOOL unityIsPaused;
+ (instancetype)sharedInstance;
@end
LARManager.m1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@implementation LARManager
+ (instancetype)sharedInstance
{
static LARManager *manager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[self alloc] init];
});
return manager;
}
- (instancetype)init
{
if (self = [super init]) {
self.unityIsPaused = NO;
NSLog(@"单例初始化成功");
}
return self;
}
@end
然后在iOS中声明被Unity调用的方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15extern "C"
{
// 对Unity中的unityToIOS方法进行实现
void unityToIOS(char* str){
// Unity传递过来的参数
NSLog(@"%s",str);
UnityPause(true);
// 跳转到IOS界面,Unity界面暂停
[LARManager sharedInstance].unityIsPaused = YES;
// GetAppController()获取appController,相当于self
// UnityGetGLView()获取UnityView,相当于_window
// 点击按钮后跳转到IOS界面,设置界面为IOS界面
GetAppController().window.rootViewController = GetAppController().vc;
}
}
在Unity中调用1
2
3
4
5
6
7
8[DllImport("__Internal")]
private static extern void unityToIOS (string str);
// 按钮点击后切换到iOS界面发送一个字符串
public void ButtonClick()
{
unityToIOS("Hello iOS");
}
实现效果:
Unity向iOS传值
第一种方法
在上个例子中已经展示了Unity向iOS传值的方法
在iOS中在extern "C"
中声明方法,然后在Unity中添加方法属性并添加标签[DllImport("__Internal")]
然后就可以直接调用了
第二种方法
在Unity项目中添加Test.h
Test.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16Test.h
extern "C"
{
extern void outputAppendString (char *str1, char *str2);
}
Test.m
void outputAppendString (char *str1, char *str2)
{
NSString *string1 = [[NSString alloc] initWithUTF8String:str1];
NSString *string2 = [[NSString alloc] initWithUTF8String:str2];
NSLog(@"###%@", [NSString stringWithFormat:@"%@ %@", string1, string2]);
}
然后两个文件Include Platforms
设置为iOS
然后添加一个按钮绑定事件1
2
3
4
5
6
7
8
9// 导入OC文件
[DllImport("__Internal")]
static extern void outputAppendString (string str1, string str2);
public void ButtonClickCalliOS()
{
outputAppendString("Hello", "World");
}
实现效果:
iOS向Unity传值
iOS向Unity传值主要通过void UnitySendMessage(const char* obj, const char* method, const char* msg);
这个方法
这个方法可以传入三个参数:
- 参数一为unity脚本挂载的gameobject
- 参数二为unity脚本中要调用的方法名
- 参数三为传递的数据,*注意:传递的数据只能是char 类型
总结
总之就是删除Unity默认的启动时机
然后再通过自定义的时机跳转到Unity界面 或着跳回到原生界面
甚至可以用iOS的原生控件去操作Unity的对象
这样 iOS部分的开发 和 Unity部分的开发就可以同时进行了
其它
项目地址:
https://github.com/Lafree317/iOS-Unity-Bridge
参考文章:
iOS与Unity3d交互-Larrycal:
https://www.jianshu.com/p/4c49655aff8b
iOS 与 unity3D 交互整合的那些事:
https://juejin.im/entry/58abd6df2f301e006c3be2f4
随缘更新RN/Week或其它移动端框架和Unity的交互